﻿/*
Copyright 2009 Matías Fidemraizer (www.matiasfidemraizer.com).

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using System;

namespace Comkarl.Architecture.Patterns
{
    /// <summary>
    /// Represents the base class for a logical instance for a pattern implementation.
    /// </summary>
    /// <typeparam name="TIdentifierName">
    /// The type for the identifier's name.
    /// </typeparam>
    public abstract class PatternInstance<TIdentifierName> : IEquatable<PatternInstance<TIdentifierName>>, IDisposable, IIdentifiable<PatternInstanceIdentifier<TIdentifierName>, TIdentifierName> 
        where TIdentifierName : IEquatable<TIdentifierName>
    {
        #region "Fields"
        /// <summary>
        /// Retrieves the identifier's for the instance.
        /// </summary>
        private readonly PatternInstanceIdentifier<TIdentifierName> id;
        #endregion

        #region "Constructors"
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="id">
        /// The identifier for the current instance.
        /// </param>
        public PatternInstance(PatternInstanceIdentifier<TIdentifierName> id)
        {
            this.id = id;
        }
        #endregion

        #region "Properties"
        /// <summary>
        /// Gets the identifier for the current instance.
        /// </summary>
        public PatternInstanceIdentifier<TIdentifierName> ID
        {
            get
            {
                return id;
            }
        }
        #endregion

        #region "Abstract methods"
        /// <summary>
        /// In a subclass which overrides it, performs tasks that are oriented to
         /// </summary>
        public abstract void Dispose();

        /// <summary>
        /// In a subclass which overrides it, performs tasks that are oriented to
        /// initialize the instance's-related resources.
        /// </summary>
        public abstract void WarmUp();
        #endregion

        #region IEquatable<PatternInstance<TIdentifierName>> Members

        /// <summary>
        /// Determines if a provided pattern instance is the same than the current context's one.
        /// </summary>
        /// <param name="other">
        /// A pattern instance.
        /// </param>
        /// <returns>
        /// A boolean value indicating if the provided pattern instance is the same than the current context's one.
        /// </returns>
        public bool Equals(PatternInstance<TIdentifierName> other)
        {
            // A pattern instance equals to other one if both have the same identifier.
            return this.ID == other.ID;
        }

        #endregion

        /// <summary>
        /// Overrides the equality operator.
        /// </summary>
        /// <param name="leftPart">
        /// The left part of the equality.
        /// </param>
        /// <param name="rightPart">
        /// The right part of the equality.
        /// </param>
        /// <returns>
        /// A boolean value indicating if both parts are the same pattern instance.
        /// </returns>
        public static bool operator ==(PatternInstance<TIdentifierName> leftPart, PatternInstance<TIdentifierName> rightPart)
        {
            if (ReferenceEquals(leftPart, rightPart))
            {
                return true;
            }

            try
            {
                return leftPart.Equals(rightPart);
            }
            catch (NullReferenceException)
            {
                return false;
            }
        }

        /// <summary>
        /// Determines de non-equality operator.
        /// </summary>
        /// <param name="leftPart">
        /// The left part of the equality.
        /// </param>
        /// <param name="rightPart">
        /// The right part of the equality.
        /// </param>
        /// <returns>
        /// A boolean value indicating if both parts are the same pattern instance.
        /// </returns>
        public static bool operator !=(PatternInstance<TIdentifierName> leftPart, PatternInstance<TIdentifierName> rightPart)
        {
            return !(leftPart == rightPart);
        }

        public override bool Equals(object obj)
        {
            return Equals((PatternInstance<TIdentifierName>)obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

    }
}